<!DOCTYPE html>
<html lang="zh">
  <head>
  <meta charset="UTF-8">
  <title>高阶纹理</title>
  <style type="text/css">
		body {
			margin: 0;
			overflow: hidden;		
		}
	</style>
  <script type="text/javascript" src="assets/javascripts/three.js"></script>
  <script type="text/javascript" src="assets/javascripts/dat.gui.min.js"></script>
  <script type="text/javascript" src="assets/javascripts/stats.min.js"></script>
  <script type="text/javascript" src="assets/javascripts/OrbitControls.js"></script>
  <script type="text/javascript" src="assets/javascripts/EffectComposer.js"></script>
  <script type="text/javascript" src="assets/javascripts/RenderPass.js"></script>
  <script type="text/javascript" src="assets/javascripts/CopyShader.js"></script>
  <script type="text/javascript" src="assets/javascripts/ShaderPass.js"></script>
  <script type="text/javascript" src="assets/javascripts/MaskPass.js"></script>
  <script type="text/javascript">
    var scene, camera, renderer;
    var stats, control;
    var sceneBG, cameraBG, composer;
	

    function init () {
      scene = new THREE.Scene();

      camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
      camera.position.set(0, 20, 40);
      camera.lookAt(scene.position);

      renderer = new THREE.WebGLRenderer( {antialias: true} );
      renderer.setClearColor(0x000000, 1.0);
      renderer.setSize(window.innerWidth, window.innerHeight);

      var earthGeometry = new THREE.SphereGeometry( 15, 50, 50 ); 
      // var sphereMaterial = new THREE.MeshNormalMaterial();
      var earthMaterial = createEarthMaterial();
      var earth = new THREE.Mesh(earthGeometry, earthMaterial);
      earth.name = "earth";
      scene.add(earth);

      var cloudGeometry = new THREE.SphereGeometry( earthGeometry.parameters.radius * 1.01, 
        earthGeometry.parameters.widthSegments, earthGeometry.parameters.heightSegments ); 
      // var sphereMaterial = new THREE.MeshNormalMaterial();
      var cloudMaterial = createCloudMaterial();
      var cloud = new THREE.Mesh(cloudGeometry, cloudMaterial);
      cloud.name = "cloud";
      scene.add(cloud);


      camera.lookAt(earth.position);
      cameraControl = new THREE.OrbitControls(camera);

      var boxGeometry = new THREE.BoxGeometry(5, 5, 5);
      var boxMaterial = new THREE.MeshNormalMaterial();
      var box = new THREE.Mesh(boxGeometry, boxMaterial);
      box.name = 'box';
      box.position.set(20, 0, 0);
      scene.add(box);

      var lineXGeometry = new THREE.Geometry();
      var lineXMaterial = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
      var color1 = new THREE.Color( 0x444444 ), color2 = new THREE.Color( 0xFF0000 );

      // 线的材质可以由2点的颜色决定
      var p1 = new THREE.Vector3( 25, 0, 0 );
      var p2 = new THREE.Vector3(  -25, 0, 0 );
      lineXGeometry.vertices.push(p1);
      lineXGeometry.vertices.push(p2);
      lineXGeometry.colors.push( color1, color2 );

      var lineX = new THREE.Line( lineXGeometry, lineXMaterial, THREE.LinePieces );
      lineX.name = 'lineX';
      // scene.add(lineX);

      var lineYGeometry = new THREE.Geometry();
      var lineYMaterial = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );

      // 线的材质可以由2点的颜色决定
      p1 = new THREE.Vector3( 0, 25, 0 );
      p2 = new THREE.Vector3(  0, -25, 0 );
      lineYGeometry.vertices.push(p1);
      lineYGeometry.vertices.push(p2);
      lineYGeometry.colors.push( color1, color2 );

      var lineY = new THREE.Line( lineYGeometry, lineYMaterial, THREE.LinePieces );
      // scene.add(lineY);

      var lineZGeometry = new THREE.Geometry();
      var lineZMaterial = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );

      // 线的材质可以由2点的颜色决定
      p1 = new THREE.Vector3( 0, 0, 25 );
      p2 = new THREE.Vector3(  0, 0, -25 );
      lineZGeometry.vertices.push(p1);
      lineZGeometry.vertices.push(p2);
      lineZGeometry.colors.push( color1, color2 );

      var lineZ = new THREE.Line( lineZGeometry, lineZMaterial, THREE.LinePieces );
      lineZ.name = 'lineZ';
      // scene.add(lineZ);

      control = new function() {
        this.rotationSpeedX = 0.005;
        this.rotationSpeedY = 0.005;
      };
      addControlGui(control);
      addStats();
      initLight();


      createSceneBackground();
      createBackgroundCamera();
      setupComposer();

      document.body.appendChild(renderer.domElement);
      render();
    }

    function addStats() {
      stats = new Stats();
      stats.setMode(0);

      stats.domElement.style.position = 'absolute';
      stats.domElement.style.left = '0px';
      stats.domElement.style.top = '0px';

      document.body.appendChild(stats.domElement);
    }

    function createBackgroundCamera () {
      cameraBG = new THREE.OrthographicCamera(-window.innerWidth, window.innerWidth, window.innerHeight, -window.innerHeight, -10000, 10000);
      cameraBG.position.z = 50;
    }

    function setupComposer () {
      // setup the passes
      var bgPass = new THREE.RenderPass(sceneBG, cameraBG);
      var renderPass = new THREE.RenderPass(scene, camera);
      renderPass.clear = false;
      var effectCopy = new THREE.ShaderPass(THREE.CopyShader);
      effectCopy.renderToScreen = true;
      // add these passes to the composer
      composer = new THREE.EffectComposer(renderer);
      composer.addPass(bgPass);
      composer.addPass(renderPass);
      composer.addPass(effectCopy);
    }

    function createSceneBackground() {
      sceneBG = new THREE.Scene();
      var bgMaterial = new THREE.MeshBasicMaterial( {map: THREE.ImageUtils.loadTexture("assets/images/starry_background.jpg"), depthTest: false} );
      var bgGeometry = new THREE.PlaneGeometry( 1, 1 );

      var background = new THREE.Mesh(bgGeometry, bgMaterial);

      background.position.z = -100;
      background.scale.set(window.innerWidth * 2, window.innerHeight * 2, 1);
      sceneBG.add(background);
    }

    function createEarthMaterial() {
      var earthTexture = new THREE.ImageUtils.loadTexture("assets/images/earthmap4k.jpg");
      // var earthMaterial = new THREE.MeshBasicMaterial();
      var earthMaterial = new THREE.MeshPhongMaterial();
      earthMaterial.map = earthTexture;

      var earthNormalMap = new THREE.ImageUtils.loadTexture("assets/images/earth_normalmap_flat4k.jpg");
      earthMaterial.normalMap = earthNormalMap;
      earthMaterial.normalScale = new THREE.Vector2( 0.5, 0.7 );

      var earthSpecularMap = new THREE.ImageUtils.loadTexture("assets/images/earthspec4k.jpg");
      earthMaterial.specularMap = earthSpecularMap;
      earthMaterial.specular = new THREE.Color( 0x262626 );

      return earthMaterial;
    }
    function createCloudMaterial() {
      var cloudTexture = new THREE.ImageUtils.loadTexture("assets/images/fair_clouds_4k.png");

      var cloudMaterial = new THREE.MeshPhongMaterial();
      cloudMaterial.map = cloudTexture;
      cloudMaterial.transparent = true;

      return cloudMaterial;
    }

    function initLight() {
      var directionalLight = new THREE.DirectionalLight( 0xffffff, 1);
      directionalLight.position.set(100, 10, 50);
      scene.add(directionalLight);

      var ambientLight = new THREE.AmbientLight( 0x111111, 1 );
      // scene.add(ambientLight);
    }

    function addControlGui(controlObject) {
        var gui = new dat.GUI();
        gui.add(controlObject, 'rotationSpeedX', -0.01, 0.01);
        gui.add(controlObject, 'rotationSpeedY', -0.01, 0.01);
    }

    function render () {
      var earth = scene.getObjectByName('earth');
      var cloud = scene.getObjectByName('cloud');
      // var lineX =  scene.getObjectByName('lineX');
      // var lineZ =  scene.getObjectByName('lineZ');
      earth.rotation.y += control.rotationSpeedY - 0.001;
      cloud.rotation.y += control.rotationSpeedY;
      // lineX.rotation.y += control.rotationSpeedY;
      // lineZ.rotation.y += control.rotationSpeedY;
			
      // earth.rotation.x += control.rotationSpeedX;
      stats.update();
      cameraControl.update();

      renderer.autoClear = false;
      composer.render();

      // renderer.render(scene, camera);
      requestAnimationFrame(render);
    }
    window.onload = init;
  </script>
  </head>
  <body>
</body>
</html>